# -*- coding: UTF-8 -*-

import gtk
import os.path

class CodeForm:
    def __init__(self, name=None, code=None, display = 0):
        self.name = name
        self.code = code
        self.display = display
        
    def make(self):
        vbox = gtk.VBox()
        # label
        label_hbox = gtk.HBox(spacing=5)
        label = gtk.Label('Label')
        label_hbox.pack_start(label)
        label.show()
        self.label_entry = gtk.Entry()
        if not self.name is None:
            self.label_entry.set_text(self.name)
        label_hbox.pack_start(self.label_entry)
        self.label_entry.show()
        label_hbox.show()
        vbox.pack_start(label_hbox)
        #code
        textview = gtk.TextView()
        textview.set_wrap_mode(gtk.WRAP_CHAR)
        textview.set_size_request(300, 70)
        self.textbuffer = textview.get_buffer()
        if not self.code is None:
            self.textbuffer.set_text(self.code)
        textview.show()
        vbox.pack_start(textview)
        # help
        help_label1 = gtk.Label('You can use:')
        help_label2 = gtk.Label('%image% , %ad% , %thumb% , %filename%')
        vbox.pack_start(help_label1)
        vbox.pack_start(help_label2)
        help_label1.show()
        help_label2.show()
        # How display
        hd_hbox = gtk.HBox(spacing=5)
        hd_label = gtk.Label('How display:')
        hd_hbox.pack_start(hd_label)
        hd_label.show()
        button = gtk.RadioButton(None, "Entry")
        button.connect("toggled", self.__change_display, 0)
        if self.display == 0:
            button.set_active(True)
        hd_hbox.pack_start(button)
        button.show()
        button = gtk.RadioButton(button, "Text View")
        button.connect("toggled", self.__change_display, 1)
        if self.display == 1:
            button.set_active(True)
        hd_hbox.pack_start(button)
        button.show()
        hd_hbox.show()
        vbox.pack_start(hd_hbox)
        vbox.show()
        return vbox
        
    def __change_display(self, widget, data=0):
        self.display = data
        
    def get(self):
        label = self.label_entry.get_text()
        start, end =self.textbuffer.get_bounds()
        code = self.textbuffer.get_text(start, end)
        display = self.display
        if len(label) == 0:
            return None
        if len(code) == 0:
            return None
        return (label, code, display)

class AddCodeDialog:
    def make(self, parent = None):
        self.dialog = gtk.Dialog("Add", parent,
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        
        form = CodeForm()
        vbox = form.make()
        self.dialog.vbox.pack_start(vbox)
        
        errors = True
        
        while errors:
            response = self.dialog.run()
            if response == gtk.RESPONSE_ACCEPT:
                start, end = form.textbuffer.get_bounds()
                get = form.get()
                if not get is None:
                    errors = False
                    label, code, display = get
                    result = self.save(form.label_entry.get_text(),
                                   form.textbuffer.get_text(start, end),
                                   form.display)
                    self.destroy(0)
                    return result
                else:
                    info = gtk.MessageDialog(self.dialog,
                                      gtk.DIALOG_DESTROY_WITH_PARENT,
                                      gtk.MESSAGE_ERROR,
                                      gtk.BUTTONS_OK,
                                      "Please input label and code!")
                    info.run()
                    info.destroy()
            else:
                errors = False
                self.destroy(0)
                return None
        
    def save(self, label, code, display):
        return {'label': label, 'code': code, 'show': False, 'display': display}
        
    def destroy(self, event):
        self.dialog.destroy()
        return None
        
class EditCodeDialog:
    def __init__(self, index, code):
        self.index = index
        self.codeobj = code

    def make(self, parent = None):
        self.dialog = gtk.Dialog(self.codeobj['label'], parent,
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        
        form = CodeForm(self.codeobj['label'], self.codeobj['code'],
                        self.codeobj['display'])
        vbox = form.make()
        self.dialog.vbox.pack_start(vbox)
        
        response = self.dialog.run()
        if response == gtk.RESPONSE_ACCEPT:
            start, end = form.textbuffer.get_bounds()
            result = self.save(form.label_entry.get_text(),
                               form.textbuffer.get_text(start, end),
                               form.display)
            self.destroy(0)
            return result
        else:
            self.destroy(0)
            return None
        
    def save(self, label, code, display):
        self.codeobj['label'] = label
        self.codeobj['code'] = code
        self.codeobj['display'] = display
        return (self.index, self.codeobj)
        
    def destroy(self, event):
        self.dialog.destroy()
        return None

class CodesModel:
    def __init__(self, codes):
        self.codes_liststore = gtk.ListStore(str, 'gboolean')
        self.codes = codes

    def get_model(self):
        if self.codes_liststore:
            return self.codes_liststore
        else:
            return None

    def appends(self):
        for c in self.codes.data:
            self.codes_liststore.append([c['label'], c['show']])

class CodesView:
    def __init__(self, codes):
        self.codes = codes

    def make(self, model):
        hbox = gtk.HBox()
        hbox.set_spacing(5)
        self.codes_treeview = gtk.TreeView(model)
        scrolled_window = gtk.ScrolledWindow()
        scrolled_window.add_with_viewport(self.codes_treeview)
        scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        scrolled_window.set_size_request(-1, 200)
        scrolled_window.show()
        #self.codes_treeview.set_size_request(300, -1)
        self.cell = gtk.CellRendererText()
        #self.cell.set_property('editable', True) 
        #self.cell.connect('edited', self.name_edited_cb, model)
        self.cell2 = gtk.CellRendererToggle()
        self.cell2.set_property('activatable', True)
        self.cell2.connect( 'toggled', self.show_toggled_cb, model )
        self.tvcolumn = gtk.TreeViewColumn('Name', self.cell, text=0)
        self.tvcolumn.set_expand(True)
        self.tvcolumn.set_min_width(150)
        self.tvcolumn2 = gtk.TreeViewColumn('Show', self.cell2)
        self.tvcolumn2.set_expand(False)
        self.tvcolumn2.add_attribute(self.cell2, "active", 1)
        self.codes_treeview.append_column(self.tvcolumn)
        self.codes_treeview.append_column(self.tvcolumn2)
        hbox.pack_start(scrolled_window, True)
        self.codes_treeview.show()     
        # Buttons
        self.codes_vbutton_box = gtk.VButtonBox()
        self.codes_vbutton_box.set_layout(gtk.BUTTONBOX_START)
        self.codes_vbutton_box.set_spacing(5)
        hbox.pack_start(self.codes_vbutton_box, expand=False)
        add_button = gtk.Button(stock=gtk.STOCK_ADD)
        add_button.connect("clicked", self._add_code)
        add_button.show()
        up_button = gtk.Button(stock=gtk.STOCK_GO_UP)
        up_button.connect("clicked", self._up_code)
        up_button.show()
        down_button = gtk.Button(stock=gtk.STOCK_GO_DOWN)
        down_button.connect("clicked", self._down_code)
        down_button.show()
        properties_button = gtk.Button(stock=gtk.STOCK_PROPERTIES)
        properties_button.connect("clicked", self._properties_code)
        properties_button.show()
        delete_button = gtk.Button(stock=gtk.STOCK_DELETE)
        delete_button.connect("clicked", self._delete_code)
        delete_button.show()
        self.codes_vbutton_box.pack_start(add_button, expand=False)
        self.codes_vbutton_box.pack_start(up_button, expand=False)
        self.codes_vbutton_box.pack_start(down_button, expand=False)
        self.codes_vbutton_box.pack_start(properties_button, expand=False)
        self.codes_vbutton_box.pack_start(delete_button, expand=False)
        self.codes_vbutton_box.show() 
        hbox.show()
        return hbox     
        
    def _add_code(self, widget, data=0):
        dialog = AddCodeDialog()
        code = dialog.make()
        if not code is None:
            self.codes.data.append(code)
            model = self.codes_treeview.get_model()
            model.append([code['label'], code['show']])
        
    def _up_code(self, widget, data=0):
        model = self.codes_treeview.get_model()
        path, column = self.codes_treeview.get_cursor()
        if not path is None:
            iter = model.get_iter(path)
            label = model.get_value(iter, 0)
            index, code = self.codes.get_by_label(label)
            if index > 0:
                self.codes.data[index] = self.codes.data[(index-1)]
                self.codes.data[(index-1)] = code
                newpath = (path[0]-1,)
                model.swap(iter, model.get_iter(newpath))
        
    def _down_code(self, widget, data=0):
        model = self.codes_treeview.get_model()
        path, column = self.codes_treeview.get_cursor()
        if not path is None:
            iter = model.get_iter(path)
            label = model.get_value(iter, 0)
            index, code = self.codes.get_by_label(label)
            if (index+1) < len(self.codes.data):
                self.codes.data[index] = self.codes.data[(index+1)]
                self.codes.data[(index+1)] = code
                model.swap(iter, model.iter_next(iter))
        
    def _properties_code(self, widget, data=0):
        model = self.codes_treeview.get_model()
        path, column = self.codes_treeview.get_cursor()
        if not path is None:
            iter = model.get_iter(path)
            label = model.get_value(iter, 0)
            index, code = self.codes.get_by_label(label)
            dialog = EditCodeDialog(index, code)
            result = dialog.make()
            if not result is None:
                index, code = result
                self.codes.data[index] = code
                model.set_value(iter, 0, code['label'])
        
    def _delete_code(self, widget, data=0):
        model = self.codes_treeview.get_model()
        path, column = self.codes_treeview.get_cursor()
        if not path is None:
            iter = model.get_iter(path)
            label = model.get_value(iter, 0)
            index, code = self.codes.get_by_label(label)
            self.codes.data.remove(code)
            model.remove(iter)
        
    def name_edited_cb(self, cell, path, new_text, model):
        print "Change '%s' to '%s'" % (model[path][0], new_text)
        model[path][0] = new_text
        
    def show_toggled_cb(self, cell, path, model):
        model[path][1] = not model[path][1]
        iter = model.get_iter(path)
        label = model.get_value(iter, 0)
        index, code = self.codes.get_by_label(label)
        self.codes.data[index]['show'] = not self.codes.data[index]['show']

class CodesWindow:
    def __init__(self, codes):
        self.codes = codes
        
    def make(self, parent):
        self.codes_dialog = gtk.Dialog("Code", parent,
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        
        modelobj = CodesModel(self.codes)
        modelobj.appends()
        model = modelobj.get_model()
        
        viewobj = CodesView(self.codes)
        view = viewobj.make(model)
        
        self.codes_dialog.vbox.pack_start(view)
        
        response = self.codes_dialog.run()
        if response == gtk.RESPONSE_ACCEPT:
            self._save_codes()
        self.__destroy_codes_window(0)
            
    def _save_codes(self):
        self.codes.save(os.path.join(os.path.dirname(__file__), "..", 'codes.pkl'))
        
    def __destroy_codes_window(self, event):
        self.codes_dialog.destroy()
